package com.navi.loaddata.loadService.impl.edcdata;

import static com.navi.loaddata.core.errorLog.ErrorCode.ERROR_EDC_SQLEXCEPTION;

import com.navi.loaddata.core.entity.EdcDataEntity;
import com.navi.loaddata.core.etlException.ETLException;
import com.navi.loaddata.core.etlException.ETLException2;
import com.navi.loaddata.core.gpEntity.EdcConfig;
import com.navi.loaddata.core.mesEntity.SpcDcdata;
import com.navi.loaddata.core.mysqlEntity.EtlConfD;
import com.navi.loaddata.core.pojo.EdcEtlItem;
import com.navi.loaddata.core.repository.impl.GreenPlumRepositoryImpl;
import com.navi.loaddata.core.repository.impl.MesRepositoryImpl;
import com.navi.loaddata.core.util.JacksonUtil;

import com.navi.loaddata.core.util.JdbcUtil2;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import com.navi.loaddata.core.util.LoggerUtil;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.hibernate.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

/**
 * @author Matthew
 * @date 2018/4/2
 */
@Service
@Transactional(transactionManager = "secondaryPlatformTransactionManager",
        rollbackFor = {RuntimeException.class, Exception.class})
public class LoadEdcDataService {

    private static final Logger logger = LoggerFactory.getLogger(LoadEdcDataService.class);

    @Autowired
    private MesRepositoryImpl mesDao;

    @Autowired
    private GreenPlumRepositoryImpl gpDao;

    @Autowired
    private SqlUtils sqlUtils;

    @Autowired
    private AmqpTemplate rabbitTemplate;

    public int loadEdcDataMain(EtlConfD etlConfD) throws ETLException2 {
        int countSize = 0;
        Session session = gpDao.getEntityManagerSession();
        try {
            countSize = lodEdcData(session, etlConfD);
            logger.info("lodEdcData finish");
        } catch (ETLException e) {
            throw new ETLException2(ERROR_EDC_SQLEXCEPTION, e);
        }
        return countSize;
    }


    private int lodEdcData(Session session, EtlConfD etlConfD) throws ETLException {
        int countSize=0;

        String etlItemsHql = "SELECT shop_id as shopId, line_id as lineId, ope_id as opeId, subeq_id as subeqId, com_attr_name as comAttrName FROM "
            + "edc_config WHERE del_flg = 'N' GROUP BY shop_id, line_id, ope_id, subeq_id, com_attr_name";
        List<EdcDataEntity> edcDataEntities1 = new ArrayList<>();
        List<EdcDataEntity> edcDataEntities2 = new ArrayList<>();
        List<EdcEtlItem> edcEtlItems = new ArrayList<>();
        try {
            QueryRunner queryRunnerGp = JdbcUtil2.getGpProdRunner();
            edcEtlItems = queryRunnerGp.query(etlItemsHql, new BeanListHandler<>(EdcEtlItem.class));
        }catch (Exception e){
            logger.error("ERROR GET SUBEQID FROM EdcConfig");
            logger.error(LoggerUtil.stackTraceToString(e));
            throw new ETLException("ERROR GET SUBEQID FROM EdcConfig:"+e.getMessage());
        }

        for (int i = 0; i < edcEtlItems.size(); i++) {
            System.out.println("## i = " + i);
            EdcEtlItem e = edcEtlItems.get(i);

            StringBuffer edcConfhql = new StringBuffer();
            StringBuffer edcConfhql1 = new StringBuffer();
            StringBuffer edcConfhql2 = new StringBuffer();
            edcConfhql.append("from EdcConfig where delFlg='N'");
            edcConfhql.append(getHqlAndCondition("subeqId", e.getSubeqId(), ""));
            edcConfhql.append(getHqlAndCondition("shopId", e.getShopId(), ""));
            edcConfhql.append(getHqlAndCondition("lineId", e.getLineId(), ""));
            // 只允许ope可选，其他不能为空
            edcConfhql.append(getHqlAndCondition("opeId", e.getOpeId(), "AllowEmpty"));
            edcConfhql1.append(edcConfhql).append(" and resultColumn <= 'result_500' order by resultColumn");
            edcConfhql2.append(edcConfhql).append(" and resultColumn > 'result_500' order by resultColumn");

            List<EdcConfig> edcConfigs1 =new ArrayList<>();
            List<EdcConfig> edcConfigs2 =new ArrayList<>();
            try {
                edcConfigs1 = gpDao.find(EdcConfig.class, edcConfhql1.toString());
                edcConfigs2 = gpDao.find(EdcConfig.class, edcConfhql2.toString());
            }catch (Exception ex1){
                logger.error("ERROR GET INFO FROM EdcConfig");
                logger.error(LoggerUtil.stackTraceToString(ex1));
                throw new ETLException("ERROR GET INFO FROM EdcConfig WHERE subeqId='"+e+"':"+ex1.getMessage());
            }
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
            String startTime = sdf.format(etlConfD.getRunStartTimestamp().getTime());
            String endTime = sdf.format(etlConfD.getRunEndTimestamp().getTime());

            logger.info("runTime:{}", etlConfD.getRunStartTimestamp().toString());
            String  spcDataHql = "from SpcDcdata where 1 = 1 "
                + " and subfactoryname = '" + e.getShopId() +"'"
                + " and machinename = '" + e.getLineId() +"'"
                + " and timekey >= '" + startTime + "' and timekey < '" + endTime + "'";
            if (e.getSubeqId().indexOf(",") > -1) {
                String[] subEqs = e.getSubeqId().split(",");
                StringBuilder eqSql = new StringBuilder();
                for (int j = 0; j < subEqs.length; j++) {
                    if (!StringUtils.isEmpty(subEqs[j])) {
                        eqSql.append("'").append(subEqs[j]).append("',");
                    }
                }
                spcDataHql += " and unitName IN (" + eqSql.deleteCharAt(eqSql.length() - 1) + ")";
            } else {
                spcDataHql += " and unitName = '" + e.getSubeqId() + "'";
            }
            if (!StringUtils.isEmpty(e.getOpeId())) {
                spcDataHql += " and processoperationname = '" + e.getOpeId() + "'";
            }
            spcDataHql += " order by timekey ";

            List<SpcDcdata> spcDcdataEntities = new ArrayList<>();
            try {
                spcDcdataEntities = mesDao.find(SpcDcdata.class, spcDataHql);
            }catch (Exception ex2){
                logger.error("ERROR GET INFO FROM spcDcdata");
                logger.error(LoggerUtil.stackTraceToString(ex2));
                throw new ETLException("ERROR GET INFO FROM spcDcdata WHERE subeqId='"+e+"':"+ex2.getMessage());
            }
            logger.info("共发现{}条数据, 子机台:{}", spcDcdataEntities.size(), e.getSubeqId());
            for (int j = 0; j < spcDcdataEntities.size(); j++) {
                SpcDcdata s = spcDcdataEntities.get(j);
                if (s == null) {
                    logger.warn("spcDcdataEntities.get(j) 为null");
                    continue;
                }
                try {
                    QueryRunner dataSource_mes = JdbcUtil2.getMesProdRunner();
                    String dctype = s.getDctype();
                    if (null == dctype) {
                        continue;
                    }

                    String sql1 = sqlUtils.getSqlByConf(edcConfigs1, String.valueOf(s.getDcdataid()), dctype, "1");
                    edcDataEntities1 = dataSource_mes.query(sql1, new BeanListHandler<>(EdcDataEntity.class));
                    edcDataEntities1 = edcDataEntities1.stream().peek(d -> {
                        d.setRowNo((short) 1);
                        d.setEtlTimestamp(Timestamp.valueOf(LocalDateTime.now()));
                        if (StringUtils.isEmpty(e.getComAttrName())) {
                            d.setOpeTblName("edc_data_" + d.getSubeqId().toLowerCase());
                        } else {
                            d.setOpeTblName("edc_data_" + e.getComAttrName().toLowerCase());
                        }
                    }).collect(Collectors.toList());
                    this.sendEdcMQ(edcDataEntities1);

                    if (edcConfigs2.size() > 0) {
                        String sql2 = sqlUtils.getSqlByConf(edcConfigs2, String.valueOf(s.getDcdataid()), dctype, "2");
                        edcDataEntities2 = dataSource_mes.query(sql2, new BeanListHandler<>(EdcDataEntity.class));
                        edcDataEntities2 = edcDataEntities2.stream().peek(d -> {
                            d.setRowNo((short) 2);
                            d.setEtlTimestamp(Timestamp.valueOf(LocalDateTime.now()));
                            if (StringUtils.isEmpty(e.getComAttrName())) {
                                d.setOpeTblName("edc_data_" + d.getSubeqId().toLowerCase());
                            } else {
                                d.setOpeTblName("edc_data_" + e.getComAttrName().toLowerCase());
                            }
                        }).collect(Collectors.toList());
                        this.sendEdcMQ(edcDataEntities2);
                    }


                } catch (SQLException exception) {
                    exception.printStackTrace();
                    logger.error(etlConfD.getJobName() + "LoadEdcDataService:lodEdcData" + exception.getMessage());
                }
                countSize++;
            }
        }
        return countSize;
    }

    private String getHqlAndCondition(String column, String item, String type) throws ETLException{
        String result = "";
        if ("AllowEmpty".equals(type)) {
            if (!StringUtils.isEmpty(item)) {
                result =  "and " + column + " = '" + item + "' ";
            }
        } else {
            if (!StringUtils.isEmpty(item) && "".equals(type)) {
                result =  "and " + column + " = '" + item + "' ";
            } else {
                //TODO throw Exception
                throw new ETLException("厂别、线别、子机台不能为空！");
            }
        }
        return result;
    }
    private void sendEdcMQ(List<EdcDataEntity> edcDataEntities) throws ETLException {
        try {
            edcDataEntities.forEach(e ->
                    rabbitTemplate.convertAndSend("qmsExchange", "edc_data", JacksonUtil.toJSONStr(e))
            );
        } catch (Exception e) {
            throw new ETLException("LoadEdcDataService:sendEdcMQ" + e.getMessage());
        }
    }
}
